#include "abaqus_inp_parser.h"
#include <iostream>
#include <fstream>

Assembly AbaqusInpParser::parse() {
    // Read all lines at once
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "Cannot open file: " << filename << std::endl;
        return assembly;
    }
    
    std::vector<std::string> lines;
    std::string line;
    while (std::getline(file, line)) {
        lines.push_back(line);
    }
    file.close();
    
    // Parse using index-based traversal
    for (size_t i = 0; i < lines.size(); i++) {
        line = lines[i];
        
        // Remove leading/trailing whitespace
        line.erase(0, line.find_first_not_of(" \t\r\n"));
        line.erase(line.find_last_not_of(" \t\r\n") + 1);
        
        // Skip empty lines and comments
        if (line.empty() || (line.length() >= 2 && line[0] == '*' && line[1] == '*')) {
            continue;
        }
        
        // Handle part definition
        if (startsWithIgnoreCase(line, "*Part, name=")) {
            std::string part_name = line.substr(12);
            size_t comma_pos = part_name.find(',');
            if (comma_pos != std::string::npos) {
                part_name = part_name.substr(0, comma_pos);
            }
            current_part = std::make_shared<Part>(part_name);
            assembly.addPart(part_name, current_part);
            continue;
        }
        
        // Handle part end
        else if (startsWithIgnoreCase(line, "*End Part")) {
            if (current_part) {
                current_part->elemSummary();
                current_part = nullptr;
            }
            continue;
        }
        
        // Handle node data
        else if (startsWithIgnoreCase(line, "*Node")) {
            if (current_part) {
                parseNodeBlock(lines, i);
                i--; // Step back for main loop to continue
            }
            continue;
        }
        
        // Handle element data
        else if (startsWithIgnoreCase(line, "*Element")) {
            if (current_part) {
                current_elem_type = parseElementType(line);
                parseElementBlock(lines, i);
                i--; // Step back for main loop to continue
            }
            continue;
        }
        
        // Handle instance definition
        else if (startsWithIgnoreCase(line, "*Instance, name=")) {
            std::string instance_name = line.substr(16);
            std::string part_name;
            
            // Parse instance name
            size_t comma_pos = instance_name.find(',');
            if (comma_pos != std::string::npos) {
                instance_name = instance_name.substr(0, comma_pos);
            }
            
            // Convert to uppercase
            std::transform(instance_name.begin(), instance_name.end(), instance_name.begin(), ::toupper);
            
            // Parse part name
            size_t part_pos = line.find("part=");
            if (part_pos == std::string::npos) {
                part_pos = line.find("PART=");
            }
            if (part_pos != std::string::npos) {
                part_name = line.substr(part_pos + 5);
                comma_pos = part_name.find(',');
                if (comma_pos != std::string::npos) {
                    part_name = part_name.substr(0, comma_pos);
                }
            }
            
            auto part = assembly.getPart(part_name);
            if (part) {
                current_instance = std::make_shared<Instance>(part, instance_name);
                
                // Parse translation and rotation data
                if (i + 1 < lines.size()) {
                    std::string next_line = lines[i + 1];
                    next_line.erase(0, next_line.find_first_not_of(" \t\r\n"));
                    next_line.erase(next_line.find_last_not_of(" \t\r\n") + 1);
                    
                    if (!next_line.empty() && next_line[0] != '*') {
                        auto translate = parseTranslate(next_line);
                        current_instance->setTranslation(translate);
                        i++; // Consume this line
                        
                        // Check for rotation data
                        if (i + 1 < lines.size()) {
                            next_line = lines[i + 1];
                            next_line.erase(0, next_line.find_first_not_of(" \t\r\n"));
                            next_line.erase(next_line.find_last_not_of(" \t\r\n") + 1);
                            
                            if (!next_line.empty() && next_line[0] != '*') {
                                auto rotation = parseRotate(next_line);
                                if (!rotation.empty()) {
                                    current_instance->setRotation(rotation);
                                }
                                i++; // Consume this line
                            }
                        }
                    }
                }
                
                assembly.addInstance(current_instance);
            }
            continue;
        }
        
        // Handle instance end
        else if (startsWithIgnoreCase(line, "*End Instance")) {
            current_instance = nullptr;
            continue;
        }
    }
    
    return assembly;
}